using CodePlex.TfsLibrary.ObjectModel;
using CodePlex.UnitTestUtility;
using Xunit;

namespace CodePlex.CodePlexClientLibrary
{
    public class StatusViewPresenterTest
    {
        public class DoAdd
        {
            [Fact]
            public void CallsTfsEngine()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");

                presenter.DoAdd(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.Engine.Add_LocalPath);
                Assert.False(presenter.Engine.Add_Recursive);
            }

            [Fact]
            public void CallsViewToDisplayErrorWithFailure()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                presenter.Engine.Add__CallbackData[0].SourceItemResult = SourceItemResult.E_FileNotFound;

                presenter.DoAdd(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.View.DisplayError_Path);
                Assert.Equal(SourceItemResult.E_FileNotFound, presenter.View.DisplayError__Result);
            }

            [Fact]
            public void CallsViewWithNewSourceItemWhenSuccessful()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                SourceItem returnedItem = SourceItem.FromLocalPath(@"C:\Foo\bar2.txt");
                presenter.Engine.GetSourceItem__Result = returnedItem;

                presenter.DoAdd(item);

                Assert.Equal(1, presenter.View.DisplayItem__Items.Count);
                Assert.Same(returnedItem, presenter.View.DisplayItem__Items[0]);
            }
        }

        public class DoDelete
        {
            [Fact]
            public void CallsTfsEngine()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");

                presenter.DoDelete(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.Engine.Delete_LocalPath);
                Assert.True(presenter.Engine.Delete_Force);
            }

            [Fact]
            public void CallsViewToDisplayErrorWithFailure()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                presenter.Engine.Delete__CallbackData[0].SourceItemResult = SourceItemResult.E_FileNotFound;

                presenter.DoDelete(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.View.DisplayError_Path);
                Assert.Equal(SourceItemResult.E_FileNotFound, presenter.View.DisplayError__Result);
            }

            [Fact]
            public void CallsViewWithNewSourceItemWhenSuccessful()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                item.LocalItemStatus = SourceItemStatus.Unmodified;
                SourceItem returnedItem = SourceItem.FromLocalPath(@"C:\Foo\bar2.txt");
                presenter.Engine.GetSourceItem__Result = returnedItem;

                presenter.DoDelete(item);

                Assert.Equal(1, presenter.View.DisplayItem__Items.Count);
                Assert.Same(returnedItem, presenter.View.DisplayItem__Items[0]);
            }

            [Fact]
            public void ForcedDeleteIsNotAnError()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                item.LocalItemStatus = SourceItemStatus.Unmodified;
                SourceItem returnedItem = SourceItem.FromLocalPath(@"C:\Foo\bar2.txt");
                presenter.Engine.Delete__CallbackData[0].SourceItemResult = SourceItemResult.S_ForcedDelete;
                presenter.Engine.GetSourceItem__Result = returnedItem;

                presenter.DoDelete(item);

                Assert.Equal(1, presenter.View.DisplayItem__Items.Count);
                Assert.Same(returnedItem, presenter.View.DisplayItem__Items[0]);
            }
        }

        public class DoResolve
        {
            [Fact]
            public void CallsTfsEngine()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");

                presenter.DoResolve(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.Engine.Resolve_LocalPath);
                Assert.False(presenter.Engine.Resolve_Recursive);
            }

            [Fact]
            public void CallsViewToDisplayErrorWithFailure()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                presenter.Engine.Resolve__CallbackData[0].SourceItemResult = SourceItemResult.E_FileNotFound;

                presenter.DoResolve(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.View.DisplayError_Path);
                Assert.Equal(SourceItemResult.E_FileNotFound, presenter.View.DisplayError__Result);
            }

            [Fact]
            public void CallsViewWithNewSourceItemWhenSuccessful()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                SourceItem returnedItem = SourceItem.FromLocalPath(@"C:\Foo\bar2.txt");
                presenter.Engine.GetSourceItem__Result = returnedItem;

                presenter.DoResolve(item);

                Assert.Equal(1, presenter.View.DisplayItem__Items.Count);
                Assert.Same(returnedItem, presenter.View.DisplayItem__Items[0]);
            }
        }

        public class DoRevert
        {
            [Fact]
            public void CallsTfsEngine()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");

                presenter.DoRevert(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.Engine.Revert_LocalPath);
                Assert.True(presenter.Engine.Revert_Recursive);
            }

            [Fact]
            public void CallsViewToDisplayErrorWithFailure()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                presenter.Engine.Revert__CallbackData[0].SourceItemResult = SourceItemResult.E_FileNotFound;

                presenter.DoRevert(item);

                Assert.Equal(@"C:\Foo\bar.txt", presenter.View.DisplayError_Path);
                Assert.Equal(SourceItemResult.E_FileNotFound, presenter.View.DisplayError__Result);
            }

            [Fact]
            public void CallsViewWithNewSourceItemWhenSuccessful()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                SourceItem item = SourceItem.FromLocalPath(@"C:\Foo\bar.txt");
                SourceItem returnedItem = SourceItem.FromLocalPath(@"C:\Foo\bar2.txt");
                presenter.Engine.GetSourceItem__Result = returnedItem;

                presenter.DoRevert(item);

                Assert.Equal(1, presenter.View.DisplayItem__Items.Count);
                Assert.Same(returnedItem, presenter.View.DisplayItem__Items[0]);
            }
        }

        public class Run
        {
            [Fact]
            public void CallsTfsEngineStatus()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();

                presenter.Run(@"C:\Foo");

                Assert.Equal(@"C:\Foo", presenter.Engine.Status_LocalPath);
                Assert.True(presenter.Engine.Status_Recursive);
                Assert.False(presenter.Engine.Status_IncludeServer);
            }

            [Fact]
            public void NoItems()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();

                presenter.Run(@"C:\Foo");

                Assert.False(presenter.View.DisplayError__Called);
                Assert.Empty(presenter.View.DisplayItem__Items);
            }

            [Fact]
            public void SourceItemError()
            {
                TestableStatusViewPresenter presenter = TestableStatusViewPresenter.Create();
                presenter.Engine.Status__CallbackData.Add(new SourceItemCallbackData(SourceItem.FromLocalPath(@"C:\Bar"), SourceItemResult.E_PathNotFound));

                presenter.Run(@"C:\Foo");

                Assert.Equal(@"C:\Bar", presenter.View.DisplayError_Path);
                Assert.Equal(SourceItemResult.E_PathNotFound, presenter.View.DisplayError__Result);
                Assert.Empty(presenter.View.DisplayItem__Items);
            }
        }

        class TestableStatusViewPresenter : StatusViewPresenter
        {
            public readonly StubTfsEngine Engine;
            public readonly StubStatusView View;

            TestableStatusViewPresenter(StubStatusView view,
                                        StubTfsEngine engine)
                : base(view, engine, true, true, false)
            {
                View = view;
                Engine = engine;
            }

            public static TestableStatusViewPresenter Create()
            {
                StubTfsEngine engine = new StubTfsEngine();
                engine.Status__CallbackData.Clear();
                return new TestableStatusViewPresenter(new StubStatusView(), engine);
            }
        }
    }
}